/*
**
**			Heroes IV
**	  Copyright 2001, The 3DO Company
**
**      dialog_altar.cpp
*/
// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "dialog_altar.h"

#include "adaptor_handler.h"
#include "adv_altar.h"
#include "adventure_map.h"
#include "army.h"
#include "basic_dialog.h"
#include "bitmap_group.h"
#include "bitmap_group_cache.h"
#include "bitmap_layer.h"
#include "bitmap_layer_window.h"
#include "bound_handler.h"
#include "button.h"
#include "button_cache.h"
#include "creature_select_window.h"
#include "creature_icon_window.h"
#include "dialog_magic_university.h"
#include "enum_operations.h"
#include "external_string.h"
#include "format_string.h"
#include "game_replace_keywords.h"
#include "hero.h"
#include "interface_help.h"
#include "player.h"
#include "random.h"
#include "replace_keywords.h"
#include "skill.h"
#include "skill_button.h"
#include "skill_icon.h"
#include "skill_properties.h"
#include "standard_fonts.h"
#include "text_window.h"

extern  t_button_cache g_cancel_button;
extern  t_button_cache g_ok_button;

t_bitmap_group_cache k_altars_bitmaps( "dialog.altars" );
extern t_bitmap_group_cache const   k_skill_frames;

/*
** Altar dialog constructor.  Choose hero for upgrade.
*/
t_dialog_altar::t_dialog_altar ( t_window* parent )
					: t_window( k_completely_transparent, parent )
{
}

void t_dialog_altar::init_dialog( std::vector<t_hero*> const& heroes, t_skill_type skill_type, t_stationary_adventure_object* parent_object)
{

	t_bitmap_layer const*   layer;
	t_window *              window;
	t_screen_point          origin(0,0);
	t_screen_point          point(0,0);
	t_screen_rect           rect;
    int                     i;
    t_skill                 skill;
    std::string const& name_text = parent_object->get_text ("name");
    std::string const& intro_text = parent_object->get_text ("Initial");
	t_help_block const&		help = get_help_block( "shared" );

    m_parent_ptr = parent_object;
	m_bitmaps_ptr = k_altars_bitmaps.get();
	layer = m_bitmaps_ptr->find( "background" );
	window = new t_bitmap_layer_window( layer, origin, this );

	point = m_bitmaps_ptr->find("hero_rings")->get_rect().top_left() + origin;

	m_hero_selection_window = new t_creature_toggle_window( point, this );

    m_skill_type = skill_type;
    skill.skill = m_skill_type;
    skill.level = k_mastery_basic;

	for (i = 0; i < heroes.size(); i++)
	{
		m_hero_selection_window->add( heroes[i] );

        /*
        ** Check if hero can learn.  If hero has primary skill, check if hero can learn more.
        */
        if ((heroes[i]->can_learn (skill)) && ( hero_can_learn_more_skill( skill.skill, heroes[i] ) != k_skill_none ))
    	    m_hero_selection_window->enable( i, true );
        // Can't learn primary, and there is space for one more primary.
        else if ( (!(heroes[i]->can_learn (skill))) && (heroes[i]->get_primary_skill_count() < k_primary_skill_limit) )
    	    m_hero_selection_window->enable( i, true );
        else
    	    m_hero_selection_window->enable( i, false );

	    m_hero_selection_window->set_help_text( i, heroes[i]->get_name() );
    }

	m_hero_selection_window->set_handler( bound_handler( *this, &t_dialog_altar::hero_selection_change ));
	m_hero_selection_window->select_none();
	m_hero_selection_window->select_first();

    // Select default hero.
    m_selected_index = 0;
    hero_selection_change( NULL, NULL );

    // Show skill icon.
    t_screen_point          offset;
	t_bitmap_group_ptr      skill_frames = k_skill_frames.get();
    offset = skill_frames->find( "icon" )->get_rect().top_left();

	rect = m_bitmaps_ptr->find( "icon" )->get_rect() + offset;
	window = new t_skill_icon( skill, rect, this );

    // Center skill within frame.
#if (0)
    point = window->get_screen_rect().top_left();
    int half_window = rect.width()/2;
    half_window -= (window->get_width()/2);
    point += t_screen_point(half_window, 0);
    window->move( point );
#endif

    // Add frame.
    rect = m_bitmaps_ptr->find( "icon" )->get_rect();
    layer = skill_frames->find( "released" );
    offset = layer->get_rect().top_left();
	window = new t_bitmap_layer_window( layer, rect.top_left() - offset, this );

    /*
    ** Text windows.
    */
	t_text_window* text_window_ptr;

    // Title.
	rect = m_bitmaps_ptr->find( "title" )->get_rect() + origin;
	text_window_ptr = new t_text_window( get_font( 20 ), rect, this, name_text, t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_drop_shadow( false );

    // Skill name text.
	rect = m_bitmaps_ptr->find( "icon_text" )->get_rect() + origin;
	text_window_ptr = new t_text_window( get_font(rect.height()/2), rect, this, get_name( skill.skill ), t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_center_vertical();

	/*
    ** Add the intro text.
    */
	m_intro_text = intro_text;
	rect = m_bitmaps_ptr->find( "text" )->get_rect() + origin;
	text_window_ptr = new t_text_window( get_font( 20 ), rect, this, m_intro_text, t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_drop_shadow( false );

    /*
    ** Create buttons.
    */
	t_button            *button_ptr;
	rect = m_bitmaps_ptr->find( "ok_button" )->get_rect();
	button_ptr = new t_button( g_ok_button.get(), rect.top_left(), this );
	button_ptr->set_click_handler( bound_handler( *this, &t_dialog_altar::close_click ));
	set_help( button_ptr, help, "ok" );

	rect = m_bitmaps_ptr->find( "cancel_button" )->get_rect();
	button_ptr = new t_button( g_cancel_button.get(), rect.top_left(), this );
	button_ptr->set_click_handler( bound_handler( *this, &t_dialog_altar::cancel_click ));
	set_help( button_ptr, help, "cancel" );
    
    /*
    ** Set the position and display the window.
    */
	t_screen_rect parent_rect = get_parent()->get_client_rect();
    
	rect = m_bitmaps_ptr->get_rect();
	rect += (parent_rect.size() - rect.size()) / 2;
	init( rect );
}

// Select a hero.
void t_dialog_altar::hero_selection_change( t_creature_select_window*, t_creature_stack* )
{
	int i;

	for (i = 0; i < m_hero_selection_window->get_count(); i++)
    {
		if ((m_hero_selection_window->is_enabled(i)) && (m_hero_selection_window->is_selected(i)))
        {
		    m_hero_ptr = m_hero_selection_window->get_creature(i)->get_hero();
		    m_selected_index = i;
        }
    }

}

static t_external_string const k_text_learned( "learned.misc" );

/*-------------------------------------------------------------------*\
** Clicked on the close button.  Give hero randomly chosen skill
** from skill type.
\*-------------------------------------------------------------------*/
void t_dialog_altar::close_click( t_button* button )
{
	t_adventure_map const &     map = *m_parent_ptr->get_map();
	t_skill_set const &			allowed_skills = map.get_allowed_skills();
	std::vector<t_skill>	    available_skills;
    t_skill_type                primary_skill;
    t_skill_type                cur_skill_type;
    t_skill                     basic_skill;
    int                         skill_index;
    
    basic_skill.skill = m_skill_type;
    basic_skill.level = k_mastery_basic;
    
    if (m_hero_ptr->get_skill( m_skill_type ) == k_mastery_none && m_hero_ptr->can_learn(basic_skill))
	{
        available_skills.push_back( basic_skill );
	}
    else
    {
        // Randomly pick a skill - we already know hero can learn this skill..
        for (cur_skill_type = k_skill_tactics; cur_skill_type < k_skill_count; enum_incr( cur_skill_type ))
        {
            primary_skill = (get_primary_skill (cur_skill_type));

            // Make sure this has the same primary skill.
            if (primary_skill != m_skill_type)
                continue;

            // Hero can't learn any more of this skill.
			t_skill_mastery cur_mastery = m_hero_ptr->get_skill( cur_skill_type );
    	    if ( cur_mastery == k_mastery_grand_master )
                continue;
 
			t_skill learned_skill( cur_skill_type, enum_add( cur_mastery, 1 ) );

            if (!(m_hero_ptr->can_learn (learned_skill)))
                continue;
        
            available_skills.push_back( learned_skill );
        }
    }

	// Try to avoid learning basic level of disallowed skills. Never prevent hero from getting some benefit though
	std::vector< t_skill > original_available_skills( available_skills );
	skill_index = 0; 
	
	while (skill_index < available_skills.size())
	{
		if (    allowed_skills[ available_skills[ skill_index ].skill ] 
			 || available_skills[ skill_index ].level > k_mastery_basic )
		{
			skill_index++;
		}
		else
		{
			available_skills.erase( available_skills.begin() + skill_index );
		}
	}

	// If all skills disallowed, ignore allowed skills
	if ( available_skills.empty() )
		available_skills = original_available_skills;

    // Randomly pick a skill from available list.
    skill_index = (random( 0, (available_skills.size()-1) ));
   
    // Only 1, but needs to be vector for display_skill.
    std::vector<t_hero*>    learned_hero;

    learned_hero.push_back(m_hero_ptr);

    display_skill(available_skills[skill_index], this, learned_hero, m_parent_ptr->get_text("learned_skill"));

    // Hero learns it.
    m_hero_ptr->learn_skill (available_skills[skill_index], true );

	m_return_value = true;
	close();
}

void t_dialog_altar::cancel_click( t_button* button )
{
	m_return_value = false;
	close();
}
